// Copyright (C) ZHENG Zhong <heavyzheng nospam-at gmail D0T com>
//
// $Id: date.hpp 225 2008-09-12 17:43:02Z heavyzheng $
//

#ifndef ZZHENG_QUANT_DATES_DATE_HPP_20080602__
#define ZZHENG_QUANT_DATES_DATE_HPP_20080602__

#include <zzheng/quant/dates/config.hpp>

#ifdef ZZHENG_MSVC
#  pragma warning(push)
#  pragma warning(disable: 4127 4244 4511 4512 4701)
#endif // ZZHENG_MSVC

// Include boost::date, no IO just types.
#include "boost/date_time/gregorian/gregorian_types.hpp"

#ifdef ZZHENG_MSVC
#  pragma warning(pop)
#endif // ZZHENG_MSVC

#include <string>

namespace zzheng {
namespace quant {
namespace dates {

    //! This class represents a date.
    class date {

    public:

        enum weekday_type {
            monday    = 1,
            tuesday   = 2,
            wednesday = 3,
            thursday  = 4,
            friday    = 5,
            saturday  = 6,
            sunday    = 7,
        };

        typedef unsigned short  day_type;   //!< Day of month type from 1 to 31.
        typedef unsigned short  month_type; //!< Month type from 1 to 12.
        typedef unsigned short  year_type;  //!< Year type.

    public:

        ////////////////////////////////////////////////////////////////////////////////////////////
        // constructors
        //

        //! Default constructor. The date constructed in this way are set to empty.
        explicit date();

        //! Constructs a date using the specified values.
        //! \param year    the year.
        //! \param month   the month.
        //! \param day     the day of month.
        //! \throws std::exception  if any of the values is out of range.
        explicit date(year_type year, month_type month, day_type day);

        //! Constructs a date from boost::gregorian::date.
        //! \param rhs  the boost::gregorian::date object to copy from.
        explicit date(const boost::gregorian::date& rhs);

        // Use auto-generated copy constructor.
        // Use auto-generated copy assignment.
        // Use auto-generated destructor.

        ////////////////////////////////////////////////////////////////////////////////////////////
        // comparison operators
        //

        bool operator==(const date& rhs) const;

        bool operator<(const date& rhs) const;

        bool operator!=(const date& rhs) const;

        bool operator>(const date& rhs) const;

        bool operator<=(const date& rhs) const;

        bool operator>=(const date& rhs) const;

        ////////////////////////////////////////////////////////////////////////////////////////////
        // increment/decrement operators
        //

        //! Pre-increment operator.
        date& operator++();

        //! Post-increment operator.
        date operator++(int);

        //! Pre-decrement operator.
        date& operator--();

        //! Post-decrement operator.
        date operator--(int);

        ////////////////////////////////////////////////////////////////////////////////////////////
        // plus/minus operators
        //

        date operator+(int delta) const;

        date operator-(int delta) const;

        ////////////////////////////////////////////////////////////////////////////////////////////
        // member functions
        //

        void swap(date& rhs);

        bool empty() const;

        int julian_day() const;

        year_type year() const;

        month_type month() const;

        day_type day() const;

        weekday_type weekday() const;

        bool is_end_of_month() const;

        date end_of_month() const;

        date& add_days(int delta);

        date& add_weeks(int delta);

        date& add_months(int delta, bool end_of_month = true);

        date& add_years(int delta, bool end_of_month = true);

        std::string str() const;

    private:

        boost::gregorian::date date_; //!< The underlying object.

    }; // class date

} // namespace zzheng::quant::dates
} // namespace zzheng::quant
} // namespace zzheng

#endif // ZZHENG_QUANT_DATES_DATE_HPP_20080602__




